package com.codehelper;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.codehelper.freemarker.CustomFreemarkerTemplateEngine;
import run.GenarateForEngineeringRailway;

import java.io.File;
import java.util.*;

/**
 * @author xieqiang
 * @date 2025/3/6
 * @since java 1.8
 */
public class CodeGenerator {


    /**==设置数据库连接信息===*/
    String jdbcUrl = "jdbc:mysql://172.22.22.216:3306/engineering-railway-test?characterEncoding=utf8&serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true";
    String jdbcUsername = "root";
    String jdbcPwd = "archivedag";


    boolean entityExtendBase=true;
    //是否生成service代码（有些中间表不需要生成）
    boolean needService=true;

    //是否生成service接口
    boolean serviceWithInterface=false;

    //是否生成controller代码（有些中间表不需要生成）
    boolean needController=true;

    /**是否生成基于DTO,VO的接口，除非非常简单的单表的增删改查可以不生成DTO,VO，尽量生成*/
    boolean needVo=true;

    /**设置生成代码所在的根包*/
    String rootPackage = "com.qhkj.engineering.compile.xxxx";


    //Java文件所在的根目录，不包括包
    String dir="/Users/xieqiang/Documents/工作-文稿/qinhai-codes/engineering-service/compile-engineering/src/main/java";

    //mapper.xml文件所在的目录
    String xmldir = "/Users/xieqiang/Documents/工作-文稿/qinhai-codes/engineering-service/compile-engineering/src/main/resources/mapper";

    public void gen(String tableName){

        /**==设置使用的模板目录===*/
        String templatePath = "/templates/engineering";


        /**==设置过滤表前后缀==*/
        String[] prefix = new String[]{"eng_"};
        String[] suffix = new String[]{"_t"};



        /**类注释的作者*/
        String author="codeGen";

        /**是否生成swagger注解*/
        boolean swagger=true;

        /** 设置实体基类字段 */
        Set<String> BASE_ENTITY_FIELDS = new HashSet<>(Arrays.asList(new String[]{"createBy", "createTime", "updateBy", "updateTime", "remark"}));

        Map<String, Object> customParams = new HashMap<>();
        customParams.put("dbType", jdbcUrl.contains("mysql")?"mysql":"oracle");
        customParams.put("BASE_ENTITY_FIELDS", BASE_ENTITY_FIELDS);
        customParams.put("swagger",swagger);
        //是否使用mybatis-plus
        customParams.put("mapperPlus",true);
        customParams.put("entityExtendBase",entityExtendBase);
        /**== 根据需要配置是否生成各层,默认生成==*/

        customParams.put("need_service", needService);
        customParams.put("need_mapper", true);
        customParams.put("need_mapperXml", true);
        customParams.put("need_controller", needService?needController:false);


        customParams.put("need_excelVo", needVo);
        customParams.put("need_vo", needVo);
        customParams.put("need_saveDto", needVo);

        String mapperPackage=rootPackage + "." + "mapper";
        String domainPackage = rootPackage + "." + "domain";
        String dtoPackage = rootPackage + "." + "domain.dto";
        String voPackage = rootPackage + "." + "domain.vo";
        String controllerPackage = rootPackage + "." + "controller";
        String servicePackage = rootPackage + ".service";
        String serviceImplPackage = rootPackage + ".service.impl";

        /**设置代码模板生成的包、目录、文件名模式信息*/
        List<TemplateFileInfo> templateFileInfos = new ArrayList<>();
        //设置各种文件代码生成的根目录
//设置实体类的生成模板信息：使用entity模板(不需扩展名)、所在包名、生成文件的路径、文件名模式({entity}会被替换成实体类名)
        templateFileInfos.add(TemplateFileInfo.javaFile("entity", domainPackage, joinPath(dir, domainPackage), "{entity}"));
        templateFileInfos.add(TemplateFileInfo.javaFile("mapper", mapperPackage, joinPath(dir, mapperPackage), "{entity}Mapper"));
        if(serviceWithInterface) {
            templateFileInfos.add(TemplateFileInfo.javaFile("service", servicePackage, joinPath(dir, servicePackage), "{entity}Service"));
            templateFileInfos.add(TemplateFileInfo.javaFile("serviceImpl", serviceImplPackage, joinPath(dir, serviceImplPackage), "{entity}ServiceImpl"));
        }else{
            templateFileInfos.add(TemplateFileInfo.javaFile("service", servicePackage, joinPath(dir, servicePackage), "{entity}Service"));
        }
        templateFileInfos.add(TemplateFileInfo.javaFile("controller", controllerPackage, joinPath(dir, controllerPackage), "{entity}Controller"));
        templateFileInfos.add(TemplateFileInfo.otherFile("mapperXml", xmldir, "{entity}Mapper", ".xml"));
        templateFileInfos.add(TemplateFileInfo.javaFile("saveDto", dtoPackage,joinPath(dir,dtoPackage), "{entity}SaveDTO"));
        templateFileInfos.add(TemplateFileInfo.javaFile("vo", voPackage,joinPath(dir,voPackage), "{entity}VO"));
        templateFileInfos.add(TemplateFileInfo.javaFile("excelVo", voPackage,joinPath(dir,voPackage), "{entity}ExcelVO"));


        FastAutoGenerator.create(new DataSourceConfig.Builder(jdbcUrl, jdbcUsername, jdbcPwd))
                .globalConfig(builder -> {
                    builder.author(author) // 设置类上的作者注释
                            .disableOpenDir()
                            .fileOverride() // 覆盖已生成文件
                            .dateType(DateType.TIME_PACK);
                })
                .strategyConfig(builder -> {
                    builder.addInclude(tableName) // 设置需要生成的表名
                            /**==设置过滤表前缀==*/
                            .addTablePrefix(prefix).addTableSuffix(suffix);
                })
                .injectionConfig(consumer -> {
                    Map<String, String> customFile = new HashMap<>();
                    // 设置模板
                    File[] templates = new File(GenarateForEngineeringRailway.class.getResource(templatePath).getFile()).listFiles();
                    for (File template : templates) {
                        if(serviceWithInterface) {
                            if(template.getName().startsWith("serviceWithoutInterface")){
                                continue;
                            }
                        }else{
                            if(template.getName().startsWith("service.")||template.getName().startsWith("serviceImpl.")){
                                continue;
                            }
                        }
                        String k=template.getName().substring(0, template.getName().indexOf("."));
                        if(k.equals("serviceWithoutInterface")){
                            k="service";
                        }
                        customFile.put(k, templatePath + "/" + template.getName());
                    }
                    consumer.customFile(customFile);
                    consumer.customMap(customParams);

                })
                .templateEngine(
                        new CustomFreemarkerTemplateEngine(templateFileInfos))
                .execute();
    }

    private static String joinPath(String parentDir, String packageName) {

        if (!StringUtils.endsWith(parentDir, File.separator)) {
            parentDir = parentDir + File.separator;
        }

        packageName = packageName.replaceAll("\\.", "\\" + File.separator);
        return parentDir + packageName;
    }


    public CodeGenerator setJdbcUrl(String jdbcUrl) {
        this.jdbcUrl = jdbcUrl;
        return this;
    }

    public CodeGenerator setJdbcUsername(String jdbcUsername) {
        this.jdbcUsername = jdbcUsername;
        return this;
    }

    public CodeGenerator setJdbcPwd(String jdbcPwd) {
        this.jdbcPwd = jdbcPwd;
        return this;
    }

    public CodeGenerator setNeedService(boolean needService) {
        this.needService = needService;
        return this;
    }

    public CodeGenerator setNeedController(boolean needController) {
        this.needController = needController;
        return this;
    }

    public CodeGenerator setNeedVo(boolean needVo) {
        this.needVo = needVo;
        return this;
    }

    public CodeGenerator setRootPackage(String rootPackage) {
        this.rootPackage = rootPackage;
        return this;
    }

    public CodeGenerator setDir(String dir) {
        this.dir = dir;
        return this;
    }

    public CodeGenerator setXmldir(String xmldir) {
        this.xmldir = xmldir;
        return this;
    }


    public CodeGenerator setEntityExtendBase(boolean entityExtendBase) {
        this.entityExtendBase = entityExtendBase;
        return this;
    }
}
